﻿using System;
using ComLib.ComType;
using System.Collections;
using System.IO;
using LogLib;
using ProcessConfig.ConfigType;
using ProcessConfig;
using CardQCProcessor;
using Newtonsoft.Json;
using System.Text;

namespace CardPhotoQCServer.QC
{
    public class QCProcess
    {
        private QCProductFactory QCFactory = QCProductFactory.Instance;

        private Monitor _monitor = null;

        private PhotoApplyOption _applyOption = new PhotoApplyOption();

        protected string _error = "";
        public string ErrorMessage
        {
            get
            {
                return _error;
            }
        }

        public event Action AppExited;

        public void OnAppExited(string inParams)
        {
            if (AppExited != null)
            {
                AppExited();
            }
        }

        private static PhotoDirectory _dirs = (PhotoDirectory)ConfigService.GetConfig(typeof(PhotoDirectory));

        private QCRequestArgs _requestArgs = null;
        public QCRequestArgs RequestArgs
        {
            get { return _requestArgs; }
        }

        private QCHandler _handler = null;
        public QCHandler Handler
        {
            get { return _handler; }
            set { _handler = value; }
        }
        
        private string _passFilePath = "";
        public string PassFilePath
        {
            get { return _passFilePath; }
        }

        protected ArrayList _arrayQCErrors = new ArrayList();
        public ArrayList ArrayQCErrors
        {
            get { return _arrayQCErrors; }
        }

        public QCProcess()
        {
            
        }

        public void Init()
        {
            try
            {
                QCFactory.Process = this;
                _applyOption = Configs.PhoApplyOption;
                _monitor = new Monitor();
                _monitor.StartWorking();
               
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
        }

        public void Exit()
        {
            if (_monitor != null)
            {
                _monitor.StopWorking();
            }            
        }

        public string Handle(string inParams)
        {
            _monitor.SetEvent();
             string ret= OnHandling(inParams);
            _monitor.Reset();
            return ret;
        }

        private bool ParseRequsetArgs(string inputingString)
        {
            try
            {
                Log.WriteAsync("收到请求: " + inputingString);
                _requestArgs = JsonConvert.DeserializeObject<QCRequestArgs>(inputingString);
                Log.WriteAsync("解析成功!");
                return true;
            }
            catch (Exception ex)
            {
                _error = "输入参数无效，解析失败：" + ex.Message;
                Log.WriteException(ex.ToString());
                Log.WriteAsync(_error);
                return false;
            }
        }

        public string OnHandling(string inputString)
        {
            _error = "";
            if (!ParseRequsetArgs(inputString))
            {
                QCHandleResultArgs args = new QCHandleResultArgs();
                args.CallSuccess = false;
                args.RuntimeError = _error;
                return JsonConvert.SerializeObject(args);
            }
            if (RequestArgs == null)
            {
                _error = "输入参数无效，解析结果为空.";
                QCHandleResultArgs outtingArgs = new QCHandleResultArgs();
                outtingArgs.CallSuccess = false;
                outtingArgs.RuntimeError = _error;
                return JsonConvert.SerializeObject(outtingArgs);
            }
           
            // 当收到消息需要关闭应用程序时
            if (RequestArgs.Method == QCProcessMethod.ExitApp)
            {
                _error = "Exit";
                QCHandleResultArgs outtingArgs = new QCHandleResultArgs();
                outtingArgs.RequestMethod = RequestArgs.Method;
                outtingArgs.CallSuccess = true;
                OnAppExited("");
                return JsonConvert.SerializeObject(outtingArgs);
            }
            _monitor.SelectDefaultOption(RequestArgs.ApplyType);
            _monitor.SetEvent();
            QCHandleResultArgs result = null;
            DoQCHandler(out result);
            _requestArgs = null;
            return JsonConvert.SerializeObject(result);
        }
  
        public void DoQCHandler(out QCHandleResultArgs result)
        {
            result = new QCHandleResultArgs();
            result.CheckFileName = _requestArgs.CheckFileName;
            result.RequestMethod = _requestArgs.Method;
            QCFactory.SelectQCHandler(_requestArgs.ApplyType);
            int nRes = Do();
            switch (nRes)
            {
                case -99: // 检测发生了意外的错误           
                case -1: // 检测失败
                    {
                        result.CallSuccess = false;
                        result.RuntimeError = _error;
                        //detecRes.PassElems.QcDllCheck = false;
                        //Log.WriteAsync(_error);
                        //detecRes.Correction.Tips = _error;
                        return;
                    }
                case 0: // 检测通过
                    {
                        Log.WriteAsync("照片质检合格, 生成目标" + _passFilePath);
                        result.CallSuccess = true;
                        result.Pass = true;
                        result.DestFileName = _passFilePath;                        
                        return;
                    }
                case 1:  // 检测不通过
                    {
                        result.CallSuccess = true;
                        result.Pass = false;
                        result.UnpassReason = CheckError(ArrayQCErrors);                      
                        string strLog = string.Format("对照片{0}质检不通过: {1}",
                            _requestArgs.CheckFileName,
                            result.UnpassReason);
                        Log.WriteAsync(strLog);
                        return;
                    }
                default:
                    {                       
                        result.CallSuccess = false;
                        result.Pass = false;
                        result.RuntimeError = "一所照片质检发生了异常，错误的返回值: " + nRes.ToString();
                        Log.WriteAsync(result.RuntimeError);
                        //detecRes.PassElems.QcDllCheck = false;
                        return;
                    }
            }
        }


        public int Do()
        {
            if (_handler == null)
            {
                _error = "处理句柄为空!";
                return -99;
            }
            Log.WriteAsync($"质检类型:{_handler.HandleType}");
            _error = "";
            string okPath = _dirs.QCPass;
            string failPath = _dirs.QCNoPass;
            string strSrcFile = _requestArgs.CheckFileName;
            int nRes = _handler.CardPhotoQC(strSrcFile, okPath, failPath, 0);
            if (nRes == 0)
            {
                if (!CheckFileExistInPassPath(strSrcFile))
                {
                    return -99;
                }
                return 0;
            }
            if (nRes < 0)
            {
                _error = "照片质检失败, 错误代码:" + nRes.ToString(); ;
                return -1;
            }
            string strErrCode = Convert.ToString(nRes, 2);           //一所返回的错误代码
            if (_handler.CheckMode == QCMode.Optional)
            {
                if (CheckManualModifyResult(strErrCode))
                {
                    _error = "手工修改标记位合格!";
                    if (!CheckFileExistInPassPath(strSrcFile))
                    {
                        return -99;
                    }
                    return 0;
                }
            }
            GetErrDesc(strErrCode);  //一所报错信息列表
            return 1;
        }

        public bool CheckFileExistInPassPath(string strSrcFile)
        {
            _passFilePath = "";
            string fileName = Path.GetFileName(strSrcFile);
            _passFilePath = Path.Combine(_dirs.QCPass, fileName);
            if (File.Exists(_passFilePath))
            {
                _error = "照片质检通过, 检查文件存在";
                return true;
            }
            else
            {
                _error = "照片质检通过, 但是在指定路径没有找到文件: " + _passFilePath;
                return false;
            }
        }

        public bool CheckManualModifyResult(string strErrCode)
        {
            _error = "";
            if (strErrCode.Length != 31)
            {
                _error = "返回值格式错误，无法判定";
                return false;
            }

            if (strErrCode[0] == '1')
            {
                if (strErrCode[30] == '0')
                {
                    return true;
                }
            }
            return false;
        }

        protected void GetErrDesc(string strErrCode)
        {
            _arrayQCErrors.Clear();
            try
            {
                if ("0" == strErrCode)
                {
                    return;
                }
                int nIndex = 0;
                for (int i = strErrCode.Length - 1; i >= 0; i--)
                {
                    if (strErrCode[i] == '1')
                    {
                        switch (nIndex)
                        {
                            case 0:
                                _arrayQCErrors.Add("与位 31 组合，位 31 为 1 时，该位为 0 表示手工修改为合格，该位为 1 表示手工修改为不合格");
                                break;
                            case 1:
                                _arrayQCErrors.Add("图像格式不合格");
                                break;
                            case 2:
                                _arrayQCErrors.Add("图像尺寸不合格");
                                break;
                            case 3:
                                _arrayQCErrors.Add("图像文件不足20K");
                                break;
                            case 4:
                                _arrayQCErrors.Add("图像文件超过80K");
                                break;
                            case 5:
                                _arrayQCErrors.Add("两眼距离偏小");
                                break;
                            case 6:
                                _arrayQCErrors.Add("两眼距离偏大");
                                break;
                            case 7:
                                _arrayQCErrors.Add("两眼距离基本合格");
                                break;
                            case 8:
                                _arrayQCErrors.Add("头部不居中");
                                break;
                            case 9:
                                _arrayQCErrors.Add("头部基本居中");
                                break;
                            case 10:
                                _arrayQCErrors.Add("眼睛区域不合适");
                                break;
                            case 11:
                                _arrayQCErrors.Add("曝光过度");
                                break;
                            case 12:
                                _arrayQCErrors.Add("曝光不足");
                                return; ;
                            case 13:
                                _arrayQCErrors.Add("曝光基本合格");
                                break;
                            case 14:
                                _arrayQCErrors.Add("图像偏色");
                                break;
                            case 15:
                                _arrayQCErrors.Add("图像模糊");
                                break;
                            case 16:
                                _arrayQCErrors.Add("图像层次基本合格");
                                break;
                            case 17:
                                _arrayQCErrors.Add("有黑边框");
                                break;
                            case 18:
                                _arrayQCErrors.Add("噪声过大");
                                return;
                            case 19:
                                _arrayQCErrors.Add("背景不均匀");
                                break;
                            case 20:
                                _arrayQCErrors.Add("背景基本合格");
                                break;
                            case 21:
                                _arrayQCErrors.Add("局部高光");
                                break;
                            case 22:
                                _arrayQCErrors.Add("闭眼");
                                break;
                            case 23:
                                _arrayQCErrors.Add("头顶距离不合格");
                                break;
                            case 24:
                                _arrayQCErrors.Add("头长过大");
                                break;
                            case 25:
                                _arrayQCErrors.Add("头长过小");
                                break;
                            case 26:
                                _arrayQCErrors.Add("脸宽过大");
                                break;
                            case 27:
                                _arrayQCErrors.Add("脸宽过小");
                                break;
                            case 28:
                                _arrayQCErrors.Add("备用");
                                break;
                            case 29:
                                _arrayQCErrors.Add("眼睛定位失败");
                                break;
                            case 30:
                                _arrayQCErrors.Add("手工修改标志位");
                                break;
                            case 31:
                                _arrayQCErrors.Add("程序异常");
                                break;
                        }
                    }
                    nIndex++;
                }
            }
            catch (System.Exception e)
            {
                _arrayQCErrors.Add(e.Message);
            }
        }

        public static string CheckError(ArrayList alErrDesc)
        {
            string strLog;
            if (alErrDesc.Contains("曝光不足"))
            {
                strLog = string.Format("增加曝光");
                Log.WriteAsync(strLog);
            }
            else if (alErrDesc.Contains("曝光过度"))
            {
                strLog = string.Format("减少曝光");
                Log.WriteAsync(strLog);
            }
            else if (alErrDesc.Contains("头长过大"))
            {
                strLog = string.Format("头长过大");
                Log.WriteAsync(strLog);
            }
            StringBuilder buidler = new StringBuilder();
            if (alErrDesc.Count > 0)
            {
                for (int i = 0; i < alErrDesc.Count; i++)
                {
                    buidler.Append(alErrDesc[i].ToString());
                    if (i < alErrDesc.Count - 1)
                    {
                        buidler.Append(";");
                    }
                }            
            }
            return buidler.ToString();
        }
    }
}
